<?php
namespace addons\paotui\service;

use addons\paotui\library\Map;
use addons\paotui\service\Config as PaotuiConfig;
use app\admin\model\paotui\Brokeragescale;
use app\admin\model\paotui\Distanceprice;
use app\admin\model\paotui\ExtraPrice;
use app\admin\model\paotui\Generalprice;
use app\admin\model\paotui\PostDispatch;
use app\admin\model\paotui\PostOrder;
use app\admin\model\paotui\PostSocket;
use app\admin\model\paotui\UserLevel;
use app\admin\model\paotui\WeightPrice;
use think\Db;

class Post{
    public $error;
    public static $post_order_type = ['1'=>'支付','2'=>'抢单成功','3'=>'取件',"4"=>'送达'];

    public function addPost($data){
        $postModel = new \app\admin\model\paotui\Post();
        Db::startTrans();
        if($postModel->allowField(true)->save($data)){
            $userAddressModel = new UserAddress();
            $userAddressModel->refreshUpdateTime([$data['from_address_id'],$data['to_address_id']],$data['user_id']);
            Db::commit();
            return $postModel;
        }else{
            Db::rollback();
            return false;
        }
    }

    /**
     * 获取保价金额
     */
    public function getBPrice($price){
        $bpriceScale = PaotuiConfig::get('bprice_scale');
        $b_price = empty($bpriceScale)?0:bcmul($price,bcdiv($bpriceScale,100,2),2);
        return $b_price;
    }


    /**
     * 获取我的快递列表
     * @return array
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function getPostList($status,$where,$page,$limit,$field='*',$sort='status asc,id desc'){
        $total = self::getStatusModel($status)->where($where)->count();

        if($page){
            $data = collection(self::getStatusModel($status)->where($where)->page($page,$limit)->field($field)->order($sort)->select())->toArray();
        }else{
            $data = collection(self::getStatusModel($status)->where($where)->field($field)->order($sort)->select())->toArray();
        }

        foreach ($data as &$v){
            if($v['appoints_day']){
                $today = date("m-d");
                if($today == $v['appoints_day']){
                    $v['appoints_day'] = "今天";
                }

                $tomorrow = date("m-d",strtotime("+1 day",time()));
                if($tomorrow == $v['appoints_day']){
                    $v['appoints_day'] = "明天";
                }
            }
        }

        return array('data'=>$data,'total'=>$total);
    }

    private function getStatusModel($status){
        $model = new \app\admin\model\paotui\Post();

        switch ($status){
            case "1":   //全部
                $model = $model::where(['is_delete'=>0]);
                break;
            case "2":   //进行中
                $model = $model::where(["status"=>['in','2,3,4'],'is_delete'=>0]);
                break;
            case "3":   //已完成
                $model = $model::where(["status"=>5,'is_delete'=>0]);
                break;
            default:     //无条件
                $model = $model::where(["status"=>0,'is_delete'=>0]);
                break;
        }

        return $model;

    }

    /**
     * 获取详细的订单金额
     * 返回配送距离、基础配送费、超距费、超重费
     * @return float|int|mixed
     */
    public function getPostDetailPrice($from_address_id,$to_address_id,$user_id,$type=1,$weight=5){
        #判断收发件地址是否正确 start#

        if($from_address_id == $to_address_id){
            $this->error = "请选择正确的收发件地址";
            return false;
        }

        $userAddress = new \addons\paotui\service\UserAddress();
        $fromAddress = $userAddress->getAddressInfo($from_address_id,$user_id);
        if(empty($fromAddress)){
            $this->error = "请选择正确的发件地址";
            return false;
        }

        $toAddress = $userAddress->getAddressInfo($to_address_id,$user_id);
        if(empty($toAddress)){
            $this->error = "请选择正确的收件地址";
            return false;
        }
        #判断收发件地址是否正确 end#

        #获取基础价格 begin
        $generalpriceModel = new Generalprice();
        $configInfo = $generalpriceModel->where(['type'=>$type])->find();
        $general_price = empty($configInfo)?0:$configInfo['price'];
        #获取基础价格 end


        $over_distance = 0;
        $over_distance_price = 0;

        #===获取收发件经纬度之间的距离 km start#
        $map = new Map();
        $distance = $map->getCycleDistance($fromAddress['lng'].",".$fromAddress['lat'],$toAddress['lng'].",".$toAddress['lat']);

        #======获取超出里程和超出里程金额 start#
        $distancePriceModel = new Distanceprice();
        $distancePrice = $distancePriceModel->where(['type'=>$type,'min'=>['elt',$distance]])->select();

        if(!empty($distancePrice)){
            foreach($distancePrice as $k=>$v){
                //计算当前里程内价格
                $_distance = $distance<$v['max']?($distance-$v['min']):($v['max']-$v['min']);
                $over_distance = bcadd($over_distance,$_distance,2);

                $over_distance_price = bcadd($over_distance_price,ceil(bcdiv($_distance,$v['step'],1))*$v['price'],2);
            }
        }
        #======获取超出里程和超出里程金额 end#

        #===获取收发件经纬度之间的距离 km end#

        #获取超出重量和超出重量金额 start#
        $weightPriceModel = new WeightPrice();
        $weightPrice = $weightPriceModel->where(['type'=>$type,'min'=>['elt',$weight]])->select();

        $over_weight = 0;
        $over_weight_price = 0;

        if(!empty($weightPrice)){
            foreach($weightPrice as $k=>$v){
                //计算当前重量内价格
                $_over_weight = $weight<$v['max']?($weight-$v['min']):($v['max']-$v['min']);
                $over_weight = bcadd($over_weight,$_over_weight,2);

                $over_weight_price = bcadd($over_weight_price,ceil(bcdiv($_over_weight,$v['step'],1))*$v['price'],2);

            }
        }

        #获取超出重量和超出重量金额 end#

        #获取溢价金额 start#
        $extraPriceModel = new ExtraPrice();
        $extraPrice = $extraPriceModel->where(['type'=>$type])->find();

        $extra_price = empty($extraPrice['money'])?0:$extraPrice['money'];
        $extra_node = empty($extraPrice['note'])?0:$extraPrice['note'];
        #获取溢价金额 end#


        $return_data = [
            'distance'=>$distance,
            'general_price'=>$general_price,
            'over_distance'=>$over_distance,
            'over_distance_price'=>$over_distance_price,
            'over_weight'=>$over_weight,
            'over_weight_price'=>$over_weight_price,
            'extra_price'=>$extra_price,
            'extra_node'=>$extra_node
        ];

        #获取用户折扣价格 start#
        $userLevelModel = new UserLevel();
        $userLevel = $userLevelModel
            ->field("user_level.level_id,level.value")
            ->alias("user_level")
            ->join("paotui_level level","user_level.level_id = level.id")
            ->where(['user_level.user_id'=>$user_id])->find();
        if(!empty($userLevel['level_id'])) {
            if($userLevel['value'] != 0) {//value 为0不打折
                $discount_price = bcmul($general_price,bcdiv($userLevel['value'],100,2),2);
                $discount_price = bcadd($discount_price,$over_distance_price,2);
                $discount_price = bcadd($discount_price,$over_weight_price,2);
            }

            if(isset($discount_price)){
                $return_data['discount_price'] = $discount_price;
            }
        }
        #获取用户折扣价格 end#

        return $return_data;
    }

    /**
     * 获取快递员的快递列表
     * @return array
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function getPosterPostList($status,$where,$page,$limit,$field='*',$lng="",$lat="",$poster_id){
        if($status == 1){   //抢单广场
            unset($where['poster_id']);
        }

        $total = self::getPoseterStatusModel($status,$poster_id)->where($where)->count();

        switch ($status){
            case "1":   //抢单广场
            case "2":   //待揽收
                $field .= ",(2 * 6378.137* ASIN(SQRT(POW(SIN(PI()*({$lng}-from_lng)/360),2)+COS(PI()*{$lat}/180)* COS(from_lat * PI()/180)*POW(SIN(PI()*({$lat}-from_lat)/360),2)))) as from_distance,(2 * 6378.137* ASIN(SQRT(POW(SIN(PI()*({$lng}-to_lng)/360),2)+COS(PI()*{$lat}/180)* COS(to_lat * PI()/180)*POW(SIN(PI()*({$lat}-to_lat)/360),2)))) as to_distance";
                $order = "status desc,find_in_set(type,'2,1,3'),from_distance asc,to_distance asc";
                break;
            case "6":   //进行中
                $field .= ",(2 * 6378.137* ASIN(SQRT(POW(SIN(PI()*({$lng}-from_lng)/360),2)+COS(PI()*{$lat}/180)* COS(from_lat * PI()/180)*POW(SIN(PI()*({$lat}-from_lat)/360),2)))) as from_distance,(2 * 6378.137* ASIN(SQRT(POW(SIN(PI()*({$lng}-to_lng)/360),2)+COS(PI()*{$lat}/180)* COS(to_lat * PI()/180)*POW(SIN(PI()*({$lat}-to_lat)/360),2)))) as to_distance";
                $order = "find_in_set(type,'2,1,3'),updatetime desc";
                break;
            case "3":   //已揽收
            case "4":   //派送中
            case "7":   //运输中（3,4）
                $field .= ",(2 * 6378.137* ASIN(SQRT(POW(SIN(PI()*({$lng}-to_lng)/360),2)+COS(PI()*{$lat}/180)* COS(to_lat * PI()/180)*POW(SIN(PI()*({$lat}-to_lat)/360),2)))) as to_distance";
                $order = "find_in_set(type,'2,1,3'),to_distance asc";
                break;
            default:    //其他
                $order = "updatetime desc";
                break;
        }

        //设置排序
        if($lng == "" || $lat == ""){
            $field = "*";
            $order = "status asc,updatetime desc";
        }

        if($page){
            $data = collection(self::getPoseterStatusModel($status,$poster_id)->where($where)->page($page,$limit)->field($field)->orderRaw($order)->select())->toArray();
        }else{
            $data = collection(self::getPoseterStatusModel($status,$poster_id)->where($where)->field($field)->field($field)->orderRaw($order)->select())->toArray();
        }

        foreach ($data as &$v){
            if(!empty($v['from_distance'])){
                $v['from_distance'] = sprintf("%.1f",$v['from_distance']);
            }
            if(!empty($v['to_distance'])){
                $v['to_distance'] =  sprintf("%.1f",$v['to_distance']);
            }

            if($v['appoints_day']){
                $today = date("m-d");
                if($today == $v['appoints_day']){
                    $v['appoints_day'] = "今天";
                }

                $tomorrow = date("m-d",strtotime("+1 day",time()));
                if($tomorrow == $v['appoints_day']){
                    $v['appoints_day'] = "明天";
                }
            }

        }

        return array('data'=>$data,'total'=>$total);
    }

    /**
     * 按条件获取model
     * 1待抢单 2待揽收 3运输中 4派送中 5已完成 6服务中（2,3,4） -1已取消
     * @param $status
     * @return Post
     */
    private function getPoseterStatusModel($status,$poster_id){
        $model = new \app\admin\model\paotui\Post();

        switch ($status){
            case "1":   //抢单广场
                $model = $model::where(function ($query) use($status,$poster_id){
                    return $query->where(['status'=>2])->whereOr(function ($query) use ($poster_id){
                        return $query->where(['status'=>['in',[8,9]],'poster_id'=>$poster_id]);
                    });
                });
                break;
            case "2":   //待揽收
                $model = $model::where(["status"=>3]);
                break;
            case "3":   //运输中
                $model = $model::where(["status"=>4]);
                break;
            case "5":   //已送达
                $model = $model::where(["status"=>5]);
                break;
            case "6":   //服务中（2,3,4）
                $model = $model::where(["status"=>['in','3,4']]);
                break;
            case "7":   //运输中（3,4）
                $model = $model::where(["status"=>['in','4']]);
                break;
            case "-1":   //已取消
                $model = $model::where(["status"=>-1]);
                break;
            default:     //无条件
                $model = $model::where(["status"=>0]);
                break;
        }

        return $model;
    }

    /**
     * 用户获取订单详情
     */
    public function getInfoByMarket($order_no){
        $postModel = new \app\admin\model\paotui\Post();
        $postInfo = $postModel->where(['order_no'=>$order_no])->find();
        if(empty($postInfo)){
            $this->error = "订单不存在";
            return false;
        }

        /**
         * 物流轨迹
         */
        $order = [];
        $postOrderModel = new PostOrder();
        $orderList = $postOrderModel
            ->field("type,createtime")
            ->where("post_id",$postInfo['id'])
            ->order("id asc")
            ->select();
        if($orderList){
            foreach($orderList as $k=>$v){
                $order[$k]['type_name'] = \addons\paotui\service\Post::$post_order_type[$v['type']];
                $order[$k]['createtime'] = date("m-d H:i",$v['createtime']);
            }
        }

        $postInfo['order'] = $order;

        return $postInfo;
    }

    /**
     * 用户获取订单详情
     */
    public function getInfoByUser($order_no,$user_id){
        $postModel = new \app\admin\model\paotui\Post();
        $postInfo = $postModel->where(['order_no'=>$order_no,'user_id'=>$user_id])->find();
        if(empty($postInfo)){
            $this->error = "订单不存在";
            return false;
        }
        if($postInfo['poster_id']){
            $posterModel = new \app\admin\model\paotui\Poster();
            $posterInfo = $posterModel->field("poster_name,mobile")->where(['id'=>$postInfo['poster_id']])->find();
            if($posterInfo){
                $posterService = new Poster();
                $posterInfo['service_num'] = $posterService->getServiceNum($postInfo['poster_id']);
                $postInfo['poster'] = $posterInfo;
            }
        }

        if($postInfo['appoints_day']){
            $today = date("m-d");
            if($today == $postInfo['appoints_day']){
                $postInfo['appoints_day'] = "今天";
            }

            $tomorrow = date("m-d",strtotime("+1 day",time()));
            if($tomorrow == $postInfo['appoints_day']){
                $postInfo['appoints_day'] = "明天";
            }
        }



        /**
         * 物流轨迹
         */
        $order = [];
        $postOrderModel = new PostOrder();
        $orderList = $postOrderModel
            ->field("type,createtime")
            ->where("post_id",$postInfo['id'])
            ->order("id asc")
            ->select();
        if($orderList){
            foreach($orderList as $k=>$v){
                $order[$k]['type_name'] = \addons\paotui\service\Post::$post_order_type[$v['type']];
                $order[$k]['createtime'] = date("m-d H:i",$v['createtime']);
            }
        }

        $postInfo['order'] = $order;

        return $postInfo;
    }

    /**
     * 快递员获取订单详情
     */
    public function getInfoByPoster($order_no,$poster_id){
        $postModel = new \app\admin\model\paotui\Post();
        $postInfo = $postModel->where(['order_no'=>$order_no,'poster_id'=>$poster_id])->find();
        if(empty($postInfo)){
            $this->error = "订单不存在";
            return false;
        }

        if($postInfo['appoints_day']){
            $today = date("m-d");
            if($today == $postInfo['appoints_day']){
                $postInfo['appoints_day'] = "今天";
            }

            $tomorrow = date("m-d",strtotime("+1 day",time()));
            if($tomorrow == $postInfo['appoints_day']){
                $postInfo['appoints_day'] = "明天";
            }
        }

        return $postInfo;
    }

    /**
     * 拒单
     * @param $post_id
     * @param $poster_id
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function refusePost($post_id,$poster_id){
        $dispatchModel = new PostDispatch();
        $dispatchInfo = $dispatchModel->where(['post_id'=>$post_id,'poster_id'=>$poster_id,'status'=>0])->find();
        if($dispatchInfo){
           if($dispatchInfo->save(['status'=>-1])){
                $postModel = new \app\admin\model\paotui\Post();
                $postInfo = $postModel->where(['id'=>$post_id,'status'=>['in','8,9']])->find();
                if($postInfo){
                    $postInfo->save(['status'=>2,'poster_id'=>0]);
                }
               return true;
           }
        }else{
            return false;
        }
    }

    /**
     * 派单接单
     * @param $post_id
     * @param $poster_id
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function acceptPost($post_id,$poster){

        $dispatchModel = new PostDispatch();
        $dispatchInfo = $dispatchModel->where(['post_id'=>$post_id,'poster_id'=>$poster['id'],'status'=>0])->find();
        if($dispatchInfo){
            Db::startTrans();
            $postModel = new \app\admin\model\paotui\Post();
            $postInfo = $postModel->where(['id'=>$post_id])->find();

            if(empty($postInfo)){
                return false;
            }

            if($dispatchInfo->save(['status'=>1])){
                if($postInfo->save(['poster_id'=>$poster['id'],'status'=>3])){
                    self::addOrder(2,$postInfo['id'],$poster['id'],$poster['poster_name'],$poster['mobile']);

                    $sendTemplate = new SendTemplate();
                    $sendTemplate->create_receive_post($postInfo);

                    //提交事务
                    Db::commit();
                    return true;
                }else{
                    Db::rollback();

                    return false;
                }
            }
        }else{
            return false;
        }

    }

    /**
     * 抢单操作
     * @param $order_no
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function beatPost($order_no,$poster){
        //开始事务
        Db::startTrans();

        $postModel = new \app\admin\model\paotui\Post();
        $postInfo = $postModel->where(['poster_id'=>0,'status'=>2,'order_no'=>$order_no])->lock(true)->find();
        if(empty($postInfo)){
            $this->error = "订单已被抢";
            return false;
        }

        if($postInfo->save(['poster_id'=>$poster['id'],'status'=>3])){
            self::addOrder(2,$postInfo['id'],$poster['id'],$poster['poster_name'],$poster['mobile']);

            $sendTemplate = new SendTemplate();
            $sendTemplate->create_receive_post($postInfo);
            //提交事务
            Db::commit();

            return true;
        }else{
            Db::rollback();
            $this->error = "抢单失败";
            return false;
        }
    }

    /**
     * 确认取件
     * @param $order_no
     * @param $poster
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function collectPost($order_no,$poster,$images = "",$third_code="",$trird_order_no=""){

        Db::startTrans();
        //获取当前状态
        $postModel = new \app\admin\model\paotui\Post();
        $postInfo = $postModel->lock(true)->where(['status'=>3,'poster_id'=>$poster['id'],'order_no'=>$order_no])->find();
        if(empty($postInfo)){
            $this->error = "订单不存在";
            Db::rollback();
            return false;
        }

        $data = [
            'status'=>4,
            'images'=>$images,
        ];

        if($postInfo->save($data)){
            self::addOrder(3,$postInfo['id'],$poster['id'],$poster['poster_name'],$poster['mobile']);
            Db::commit();
            return true;
        }

        $this->error = "取件失败";
        Db::rollback();
        return false;
    }

    /**
     * 签收快递
     * @param $order_no
     * @param $poster
     * @param $lnglat
     * @param $image
     * @param $place
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function reachPost($order_no,$poster,$lnglat,$image){
        Db::startTrans();
        $postModel = new \app\admin\model\paotui\Post();
        $postInfo = $postModel->lock(true)->where(['status'=>['in','3,4'],'poster_id'=>$poster['id'],'order_no'=>$order_no])->find();
        if(empty($postInfo)){
            $this->error = "快递单不存在或者当前状态不能送达";
            return false;
        }

        if(empty($image)){
            $this->error = "请上传照片";
            return false;
        }

        if($postInfo->save(['status'=>5,'reach_images'=>$image,'completetime'=>time()])){
            self::addOrder(4,$postInfo['id'],$poster['id'],$poster['poster_name'],$poster['mobile']);

            $sendTemplate = new SendTemplate();
            $sendTemplate->create_post_reach($postInfo);

            Db::commit();
            return true;
        }

        $this->error="签收失败";
        return false;
    }


    /**
     *
     * @param $order_no
     * @param $transaction_id
     * @return false|void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function pay_success($order_no,$transaction_id){

        $postModel = new \app\admin\model\paotui\Post();
        $postInfo = $postModel->where(['order_no'=>$order_no,'pay_status'=>0])->find();
        if(empty($postInfo)){
            return false;
        }

        if($postInfo->save(['transaction_id'=>$transaction_id,'status'=>2,'pay_status'=>1,'paytime'=>time()])){
            $dispatch_mode = PaotuiConfig::get('dispatch_mode');
            $postIds = $postModel->where(['id'=>$postInfo['id']])->column("id");
            $data = [];
            $order_data = [];
            if($postIds){
                foreach ($postIds as $k=>$v){
                    $data[] =[
                        'post_id'=>$v,
                        'type'=>$dispatch_mode,
                        'next_send_time'=>time(),
                        'send_num'=>0,
                        'send_status'=>0,
                        'createtime'=>time()
                    ];

                    $order_data[] = [
                        'post_id'=>$v,
                        'type'=>1,
                        'createtime'=>time()
                    ];
                }
                if($data){
                    $postSocketModel = new PostSocket();
                    $postSocketModel->insertAll($data);
                }
                if($order_data){
                    $postOrderModel = new PostOrder();
                    $postOrderModel->insertAll($order_data);
                }
            }
        }
    }

    /**
     * @param $type     类型 1支付 2抢单 3取件 4送达
     * @param $post_id
     * @param $poster_id
     * @param $poster_name
     * @param $poster_mobile
     */
    public static function addOrder($type,$post_id,$poster_id,$poster_name,$poster_mobile){
        $postOrderModel = new PostOrder();
        if($postOrderModel->save([
            'type'=>$type,
            'post_id'=>$post_id,
            'poster_id'=>$poster_id,
            'poster_name'=>$poster_name,
            'poster_mobile'=>$poster_mobile
        ])){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 获取快递员可以获得佣金
     * @param $brokerage
     * @param $post_type
     * @param $poster_type
     * @param $poster_brokerage_scale
     */
    public static function poster_brokerage($brokerage,$post_type,$poster_type,$brokerage_type,$poster_brokerage_scale){
        if($poster_type == 1){
            //全职无佣金
            return 0;
        }

        if($brokerage_type == 1){
            //平台默认
            $brokerageScaleModel = new Brokeragescale();
            $brokerageScaleInfo = $brokerageScaleModel->where(['type'=>$post_type])->find();
            $scale = empty($brokerageScaleInfo)?100:$brokerageScaleInfo['scale'];
        }else{
            $scale = $poster_brokerage_scale;
        }

        return bcmul($brokerage,bcdiv($scale,100,2),2);
    }

}